using System;
using System.IO;
using System.Runtime.InteropServices;
using XLua;
using FairyGUI;

/// <summary>
/// windows系统文件选择窗口
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct OpenFileName
{
    public int structSize;
    public IntPtr dlgOwner;
    public IntPtr instance;
    public String filter;
    public String customFilter;
    public int maxCustFilter;
    public int filterIndex;
    public String file;
    public int maxFile;
    public String fileTitle;
    public int maxFileTitle;
    public String initialDir;
    public String title;
    public int flags;
    public short fileOffset;
    public short fileExtension;
    public String defExt;
    public IntPtr custData;
    public IntPtr hook;
    public String templateName;
    public IntPtr reservedPtr;
    public int reservedInt;
    public int flagsEx;
}

/// <summary>
/// windows系统文件夹选择窗口
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct OpenDialogDir
{
    public IntPtr hwndOwner;
    public IntPtr pidlRoot;
    public String pszDisplayName;
    public String title;
    public UInt32 ulFlags;
    public IntPtr lpfno;
    public IntPtr lParam;
    public int iImage;
}
public class WindowDll
{
    //链接指定系统函数       打开文件对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    public static bool GetOFN([In, Out] OpenFileName ofn)
    {
        return GetOpenFileName(ofn);
    }

    //链接指定系统函数        另存为对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
    public static bool GetSFN([In, Out] OpenFileName ofn)
    {
        return GetSaveFileName(ofn);
    }

    [DllImport("shell32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern IntPtr SHBrowseForFolder([In, Out] OpenDialogDir ofn);

    [DllImport("shell32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool SHGetPathFromIDList([In] IntPtr pidl, [In, Out] char[] fileName);
}

/// <summary>
/// 工具：windows系统文件夹/文件选择窗口
/// </summary>
public static class NativeFolderDialog
{
    /// <summary>
    /// 选择文件夹
    /// </summary>
    /// 
    [LuaCallCSharp]
    public static string ChooseWinFolder()
    {
        //使用如下：
        OpenDialogDir ofn = new OpenDialogDir();
        ofn.pszDisplayName = new string(new char[2000]); ;     // 存放目录路径缓冲区  
        ofn.title = "选择文件夹";// 标题  
        IntPtr pidlPtr = WindowDll.SHBrowseForFolder(ofn);

        char[] charArray = new char[2000];
        for (int i = 0; i < 2000; i++)
            charArray[i] = '\0';

        WindowDll.SHGetPathFromIDList(pidlPtr, charArray);
        string fullDirPath = new String(charArray);
        return fullDirPath.Substring(0, fullDirPath.IndexOf('\0'));
    }

    /// <summary>
    /// 选择应用程序文件
    /// </summary>
    /// 
    [LuaCallCSharp]
    public static string ChooseWinFile(string title,string defaultDir, string filter)
    {
        if(filter == "")
            filter = "所有文件(*.*)\0*.*\0";
        else
            filter = string.Format("(*{0}*)\0*{1}*\0", filter, filter);

        OpenFileName OpenFileName = new OpenFileName();
        OpenFileName.structSize = Marshal.SizeOf(OpenFileName);
        OpenFileName.filter = filter;
        OpenFileName.file = new string(new char[1024]);
        OpenFileName.maxFile = OpenFileName.file.Length;
        OpenFileName.fileTitle = new string(new char[64]);
        OpenFileName.maxFileTitle = OpenFileName.fileTitle.Length;
        OpenFileName.initialDir = defaultDir;
        OpenFileName.title = title;
        OpenFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008 | 0x10000000;
        if (WindowDll.GetOpenFileName(OpenFileName))
            return OpenFileName.file;
        else
            return null;
    }

    /// <summary>
    /// 打开"另存为"对话框，选择保存路径和文件名
    /// </summary>
    /// <param name="defaultFileName">默认文件名（可选）</param>
    /// <param name="filter">文件类型过滤器（如 "文本文件(*.txt)\0*.txt\0所有文件(*.*)\0*.*\0"）</param>
    /// <returns>返回用户选择的完整文件路径，如果取消则返回 null</returns>
    [LuaCallCSharp]
    public static string SaveAsFile(string defaultFileName = "", string filter = "所有文件(*.*)\0*.*\0")
    {
        OpenFileName ofn = new OpenFileName();
        ofn.structSize = Marshal.SizeOf(ofn);
        ofn.filter = filter;

        // 初始化文件名缓冲区（固定长度）
        char[] fileNameBuffer = new char[1024];
        ofn.file = new string(fileNameBuffer);
        ofn.maxFile = fileNameBuffer.Length;

        // 设置默认文件名（正确方式）
        if (!string.IsNullOrEmpty(defaultFileName))
        {
            // 将默认文件名复制到缓冲区
            defaultFileName.CopyTo(0, fileNameBuffer, 0, Math.Min(defaultFileName.Length, fileNameBuffer.Length - 1));
            ofn.file = new string(fileNameBuffer);
        }

        ofn.fileTitle = new string(new char[64]);
        ofn.maxFileTitle = ofn.fileTitle.Length;
        ofn.title = "另存为";

        // 标志位组合：
        // OFN_OVERWRITEPROMPT (0x00000002) - 如果文件已存在，提示覆盖
        // OFN_PATHMUSTEXIST (0x00000800) - 路径必须存在
        // OFN_NOCHANGEDIR (0x00000008) - 恢复当前目录
        // OFN_EXPLORER (0x00080000) - 使用新版对话框
        ofn.flags = 0x00080000 | 0x00000800 | 0x00000008 | 0x00000002;

        if (WindowDll.GetSaveFileName(ofn))
        {
            // 返回用户选择的完整路径（截取到第一个空字符）
            return ofn.file.Substring(0, ofn.file.IndexOf('\0'));
        }
        else
        {
            return null; // 用户取消
        }
    }
}